from __future__ import annotations

from dataclasses import dataclass, field
from typing import List, Optional, Dict, Any
import time
import uuid


COGNITIVE_LEVELS = ["记忆", "理解", "应用", "分析", "评价", "创造"]
DIFFICULTY_MAP = {"容易": 3, "中等": 5, "困难": 8}
SUPPORTED_TYPES = ["选择题", "填空题", "解答题", "判断题", "计算题"]


@dataclass
class KnowledgePoint:
    name: str
    description: str
    difficulty_level: int  # 1-10
    cognitive_level: str   # in COGNITIVE_LEVELS

    def validate(self) -> None:
        if not (1 <= self.difficulty_level <= 10):
            raise ValueError("difficulty_level must be in [1, 10]")
        if self.cognitive_level not in COGNITIVE_LEVELS:
            raise ValueError(f"cognitive_level must be one of {COGNITIVE_LEVELS}")


@dataclass
class FormatSpec:
    include_explanation: bool = True
    options_count: int = 4


@dataclass
class GenerationConfig:
    question_type: str
    difficulty: str  # 容易/中等/困难 或者数字字符串
    count: int
    language: str = "中文"
    format_spec: FormatSpec = field(default_factory=FormatSpec)

    def normalized_difficulty(self) -> int:
        if isinstance(self.difficulty, str) and self.difficulty.isdigit():
            value = int(self.difficulty)
            return max(1, min(10, value))
        return DIFFICULTY_MAP.get(self.difficulty, 5)

    def validate(self) -> None:
        if self.question_type not in SUPPORTED_TYPES:
            raise ValueError(f"Unsupported question_type: {self.question_type}")
        if not (1 <= self.count <= 10):
            raise ValueError("count must be in [1, 10]")
        if self.language not in ("中文", "English"):
            raise ValueError("language must be 中文 or English")


@dataclass
class Question:
    id: str
    type: str
    stem: str
    options: Optional[List[str]] = None
    correct_answer: Optional[Any] = None
    explanation: Optional[str] = None
    difficulty: int = 5
    cognitive_level: str = "理解"
    knowledge_points: List[str] = field(default_factory=list)
    quality_score: Optional[float] = None

    def to_dict(self) -> Dict[str, Any]:
        return {
            "id": self.id,
            "type": self.type,
            "stem": self.stem,
            "options": self.options,
            "correct_answer": self.correct_answer,
            "explanation": self.explanation,
            "difficulty": self.difficulty,
            "cognitive_level": self.cognitive_level,
            "knowledge_points": self.knowledge_points,
            "quality_score": self.quality_score,
        }

    @staticmethod
    def new_id() -> str:
        return str(uuid.uuid4())


@dataclass
class GenerationMetadata:
    generated_count: int
    valid_count: int
    average_quality: float
    generation_time: str

    @staticmethod
    def now_iso() -> str:
        return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())


@dataclass
class QualityResult:
    passed: bool
    score: float
    messages: List[str] = field(default_factory=list)


@dataclass
class GenerationOutput:
    questions: List[Question]
    metadata: GenerationMetadata

    def to_dict(self) -> Dict[str, Any]:
        return {
            "questions": [q.to_dict() for q in self.questions],
            "metadata": {
                "generated_count": self.metadata.generated_count,
                "valid_count": self.metadata.valid_count,
                "average_quality": self.metadata.average_quality,
                "generation_time": self.metadata.generation_time,
            },
        }